iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
0
Software Development

從 Rust 往程式底層前進系列 第 23

LD_PRELOAD hook 與 dlsym

  • 分享至 

  • xImage
  •  

LD_PRELOAD 是個用來控制 ld.so 的行為的環境變數之一,它的效果是讓 ld.so 先載入變數中指定的動態函式庫,而因為動態函式庫的符號在解析時的特性,後面的不會覆蓋掉前面的,於是就可以透過 LD_PRELOAD 蓋掉自己想覆寫的函式了

比如說像上次的範例中透過 LD_PRELOAD 來覆寫函式:

$ ./demo
Hello from libfoo

$ LD_PRELOAD="./libbar.so" ./demo
Hello from libbar

這樣的環境變數還有很多,其中有幾個比較有用的比如:

  • LD_LIBRARY_PATH: 把路徑加進 ld.so 的搜尋路徑裡,預設 ld.so 只會找 /etc/ld.so.cache 與系統的 library 的位置 (/lib/usr/lib ,如果 64 位元還會加上 64 位元的版本)
  • LD_DEBUG: 可以用來看 ld.so 的搜尋與解析過程,它有幾個參數可選

另外 LD_LIBRARY_PATH 也能透過從命令列指定的方式來使用:

$ /lib64/ld-linux-x86-64.so.2 --library-path <path> <exe>

另外有趣的是用 ld.so 來執行的程式可以不用有執行的權限

dlsym

不過在上面那個利用 LD_PRELOAD 的 hook ,如果想要呼叫原本的函式該怎麼辦呢,可以用 dlsym 來取得下一個函式:

use libc::dlsym;
use std::mem;

#[no_mangle]
pub extern "C" fn foo() {
    println!("Hello from libbar");
    let f = unsafe {
        mem::transmute::<_, extern "C" fn()>(dlsym(libc::RTLD_NEXT, "foo\0".as_ptr() as _))
    };
    f();
}

或是你也可以用 dlopen 打開特定的動態函式庫,另外這也可以用來延遲載入動態函式庫,也可以用來設計程式的外掛之類的東西


上一篇
位置無關程式碼與 GOT 和 PLT
下一篇
系統呼叫與呼叫慣例
系列文
從 Rust 往程式底層前進26
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言